<?php

// @formatter:off
/**
 * @file WCFlow.php
 * @author Alejandro Dario Simi
 * @date $Date: 2014-06-03 03:40:32 +0000 (Tue, 03 Jun 2014) $
 *
 * $Id: WCFlow.php 112 2014-06-03 03:40:32Z daemonraco@gmail.com $
 * $URL: http://wcomix.googlecode.com/svn/trunk/includes/flow/WCFlow.php $
 */
// @formatter:on

class WCFlow {
	//
	// Constants.
	const ItemTypeCollection = "CL";
	const ItemTypeComic = "CX";
	const ItemTypeImage = "IM";
	const PositionFirst = "first";
	const PositionPrevious5 = "previous5";
	const PositionPrevious = "previous";
	const PositionCurrent = "current";
	const PositionNext = "next";
	const PositionNext5 = "next5";
	const PositionLast = "last";
	const SetOfCollections = "collections";
	const SetOfComics = "comics";
	const SetOfImages = "images";
	//
	// Public class properties.
	//
	// Protected class properties.
	protected static $_Holders = false;
	protected static $_SetNamesByType = false;
	//
	// Protected properties.	
	/**
	 * @var WCConnection Database pointer shortcut.
	 */
	protected $_db;
	/**
	 * @var string Database tables' prefix shortcut.
	 */
	protected $_dbprefix;
	protected $_id = false;
	protected $_item = false;
	/**
	 * @var WCFlowItem[int][string] @todo doc
	 */
	protected $_items = array();
	protected $_loaded = false;
	protected $_ok = false;
	/**
	 * @var int[string] @todo doc
	 */
	protected $_positions = array();
//	protected $_sets = array();
	protected $_type = false;
	//
	// Magic methods.
	public function __construct($type, $id) {
		$this->_type = $type;
		$this->_id = $id;
		$this->_item = WCFlowManager::GetFlowingItem($this->_type, $this->_id);

		$this->init();

		$this->_ok = ($this->_item != false);
	}
	//
	// Public methods.
	public function getNavigationFlow($set) {
		$out = false;

		if($this->ok() && isset($this->_items[$set]) && count($this->_items[$set]) > 0) {
			$first = 0;
			$last = count($this->_items[$set]) - 1;
			$current = $this->positionOf($set);
			$current = $current < $first ? $first : $current;
			$current = $current > $last ? $last : $current;

			$previous5 = $current - 5;
			$previous = $current - 1;
			$next = $current + 1;
			$next5 = $current + 5;

			$previous5 = $previous5 < $first ? $last + $previous5 : $previous5;
			$previous = $previous < $first ? $last + $previous : $previous;
			$next = $next > $last ? $first + ($next - $last) : $next;
			$next5 = $next5 > $last ? $first + ($next5 - $last) : $next5;

			$previous5 = $previous5 < $first ? $first : $previous5;
			$previous = $previous < $first ? $first : $previous;
			$next = $next > $last ? $last : $next;
			$next5 = $next5 > $last ? $last : $next5;

			$out[self::PositionFirst] = $this->_items[$set][$first];
			$out[self::PositionPrevious5] = $this->_items[$set][$previous5];
			$out[self::PositionPrevious] = $this->_items[$set][$previous];
			$out[self::PositionCurrent] = $this->_items[$set][$current];
			$out[self::PositionNext] = $this->_items[$set][$next];
			$out[self::PositionNext5] = $this->_items[$set][$next5];
			$out[self::PositionLast] = $this->_items[$set][$last];
		}

		return $out;
	}
	public function setFlowAt(WCFlowItem &$item) {
		$out = false;

		if($this->ok()) {
			$this->load();

			$set = self::SetNameByType($item->flowItemType());

			$this->_positions[$set] = false;
			if(isset($this->_items[$set])) {
				foreach($this->_items[$set] as $position => $setItem) {
					if($setItem->id() == $item->id()) {
						$this->setFlowAtPosition($set, $position);
						break;
					}
				}
			}
		}

		return $out;
	}
	public function setFlowAtPosition($set, $position = 0) {
		$this->_positions[$set] = $position;
	}
	public function id() {
		return $this->_id;
	}
	public function item() {
		return $this->_item;
	}
	public function ok() {
		return $this->_ok;
	}
	public function positionOf($set) {
		return isset($this->_positions[$set]) ? $this->_positions[$set] : 0;
	}
	public function type() {
		return $this->_type;
	}
	//
	// Protected methods.
	protected function init() {
		//
		// Loading shortcuts.
		// @{
		$this->_db = WCConnection::Instance();
		$this->_dbprefix = $this->_db->prefix();
		// @}
//		foreach(array(self::SetOfCollections, self::SetOfComics, self::SetOfImages) as $set) {
//			$this->_sets[$set] = array();
//			foreach(array(self::PositionFirst, self::PositionPrevious5, self::PositionPrevious, self::PositionCurrent,
//			self::PositionNext, self::PositionNext5, self::PositionLast) as $position) {
//				$this->_sets[$set][$position] = false;
//			}
//		}
	}
	protected function load() {
		if(!$this->_loaded) {
			$stmt = null;
			$stmtId = __CLASS__."::".__FUNCTION__;
			if($this->_db->has($stmtId)) {
				$stmt = $this->_db->get($stmtId);
			} else {
				$query = "select  *\n";
				$query.= "from    {$this->_dbprefix}flows\n";
				$query.= "where   flw_group   = :group\n";
				$query.= " and    flw_type    = :type\n";
				$query.= " and    flw_id      = :id\n";
				$query.= "order by flw_position\n";

				$stmt = $this->_db->prepare($stmtId, $query);
			}
			// @}
			$params = array(
				":group" => $this->item()->group()->id(),
				":type" => $this->type(),
				":id" => $this->id()
			);
			if($stmt->execute($params) && $stmt->rowCount() > 0) {
				foreach($stmt->fetchAll() as $row) {
					$type = $row["flw_item_type"];
					$id = $row["flw_item_id"];
					$position = $row["flw_position"];
					$set = self::SetNameByType($type);

					if(!isset($this->_items[$set])) {
						$this->_items[$set] = array();
					}

					$item = self::GetItem($type, $id);
					if($item) {
						$this->_items[$set][$position] = $item;
					}
				}
				//
				// Cleaning gaps.
				foreach($this->_items as $set => $list) {
					$this->_items[$set] = array_values($list);
				}
			} $this->_loaded = true;
		}
	}
	//
	// Public class methods.
	//
			// Protected class methods.
	protected static function GetItem($type, $id) {
		$holder = self::HolderByType($type);
		return $holder ? $holder->item($id) : false;
	}
	protected static function HolderByType($type) {
		if(self::$_Holders === false) {
			self::$_Holders = array();
			self::$_Holders[self::ItemTypeCollection] = WCCollectionsHolder::I();
			self::$_Holders[self::ItemTypeComic
				] = WCComicsHolder::I();
			self::$_Holders[self::ItemTypeImage] = WCImagesHolder::I();
		}

		return self::$_Holders[$type];
	}
	protected static function SetNameByType($type) {
		if(self::$_SetNamesByType === false) {
			self::$_SetNamesByType = array();
			self::$_SetNamesByType[self::ItemTypeCollection] = self::SetOfCollections;
			self::$_SetNamesByType[self::ItemTypeComic] = self::SetOfComics;
			self::$_SetNamesByType[self::ItemTypeImage] = self::SetOfImages;
		}

		return self::$_SetNamesByType[$type];
	}
}
